把手机变成扫码枪:我们在SaaS小程序里解决高并发与离线缓存的实战笔记
做仓配和零售系统的朋友应该都懂,这两年用手机替代专用扫码枪的需求越来越旺。不是大家图省事,是真没办法——传统扫码枪采购成本高,型号五花八门,和现有WMS、ERP对接还要塞驱动。我们团队从去年开始,基于自研的SaaS平台,硬啃下了“手机当扫码枪”这个轻量化场景。说实话,这事儿听起来简单,不就是调摄像头识别条码吗?真做起来,最棘手的其实是高并发条码处理,以及仓库角落没信号时的离线缓存。
先说下背景,我司的SaaS平台主要服务中小微型商贸和仓配企业,本身就是云原生架构,带多租户的消息总线。选择小程序载体,是因为客户不想让员工装笨重的APP,微信扫一扫就能用最省心。但小程序运行环境限制比原生APP多得多,尤其在安卓中低端机上,CPU和内存都被微信管控得死死的,这对架构设计提出了很苛刻的要求。
高并发这关就得仔细设计。在出库流水线或者盘点高峰,一个人拿着手机哗哗地扫,每秒钟十几个条码进来的情况很常见。小程序的UI线程如果同时处理识别、渲染、网络请求,轻则掉帧,重则直接卡死白屏。我们的解法是在小程序侧启用Worker线程(是的,微信小程序支持多线程Worker),把条码识别后的数据先丢进本地内存队列,由Worker做去重和打包。同时和服务端定义了基于Protocol Buffer的批量上报协议,而不是一条一条传JSON。服务端那边用Kafka做削峰,消费服务按租户ID做一致性哈希分片,保证同一个客户的条码顺序可控。这个方案上线前,我们在内测时踩过坑:最早用WebSocket实时推,结果弱网下半open状态导致大量重连,后来果断改成短连接批量POST,反而更稳。记得有次内测,有个同事拿着千元机在电梯里狂扫,直接把UI线程搞崩了,这才倒逼我们把本地队列长度也做了限流和背压处理。
比高并发更头疼的是离线。仓库的钢结构货架对信号屏蔽特别严重,地下分拣中心经常是E信号或者纯离线。如果没网就不能扫,现场保管员能把运维电话打爆。所以我们设计了一套本地离线缓存引擎:在小程序里用FileSystemManager加内置的KV存储,模拟了一个轻量级的 append-only 日志库。每扫一个码,立刻以JSON Line格式落盘,并附加设备号、UUID、毫秒级时间戳。即便瞬间断网,扫码完全不受影响,界面只显示一个“待同步”的角标。这里头有个细节,iOS和安卓的文件写入权限不一样,我们花了将近两周调平两个平台的落盘时延,才做到真正的“扫完即存”。
等网络恢复,小程序会启动一个后台同步任务,把离线期间产生的数据块压缩后增量拉取。冲突怎么解?我们采用服务端权威 客户端补偿策略。比如同一条码离线时被误扫两次,服务端拿到后按UUID去重;如果碰到库存扣减类操作,我们用版本号乐观锁,万一离线期间服务端已被其他渠道修改,就触发告警让人工复核。去年双十二,我们一个做休闲食品的客户,整个仓用180台手机当枪,离线扫了将近四千条,网络恢复后三秒内全部对账完毕,财务那边查账零差异。
回过头看,手机当扫码枪绝不是把摄像头打开就行。高并发要靠端边协同削峰,离线要靠本地日志和最终一致性兜底。我司这套方案跑在已有SaaS底座上,客户开通子模块就能用,实施周期按天算。如果你也在做类似轻量化采集工具,欢迎交流,有些坑咱们可以一起避开。
微信号:18581869297